//
//  ACAlarm.m
//  AlarmClock
//
//  Created by kai ren on 30/08/2011.
//  Copyright 2011 none. All rights reserved.
//

#import "ACAlarm.h"

@implementation ACAlarm

@synthesize lblTime, lblRepeat, lblTitle, alarmSwitch;
@synthesize alarmIdentifier;
@synthesize title;
@synthesize sondName;
@synthesize createDate;
@synthesize fireTime;
@synthesize isActive;
@synthesize repeat;
@synthesize index;
@synthesize alarmCtrl;

#pragma mark -
#pragma mark Private

- (void)nextFire{
	NSDate *nowDate = [NSDate date];
	
	while ([self.fireTime compare:nowDate] < 0) {
		self.fireTime = [self.fireTime dateByAddingTimeInterval:aDay];
	}
	
	while ([self.fireTime timeIntervalSinceDate:nowDate] > aDay) {
		self.fireTime = [self.fireTime dateByAddingTimeInterval:-aDay];
	}
}

/** get info dictionary **/
- (NSMutableDictionary *)getInfoDictionary{
	
	NSMutableDictionary *alarmInfo = [NSMutableDictionary dictionaryWithCapacity:0];
	[alarmInfo setObject:self.alarmIdentifier forKey:ALARM_ID];
	[alarmInfo setObject:self.title forKey:ALARM_TITLE];
	[alarmInfo setObject:self.sondName forKey:ALARM_SOUND_NAME];
	[alarmInfo setObject:self.createDate forKey:ALARM_CREATE_DATE];
	[alarmInfo setObject:self.fireTime forKey:ALARM_FIRE_TIME];
	[alarmInfo setObject:[NSNumber numberWithBool:self.isActive] forKey:ALARM_IS_ACTIVE];
	[alarmInfo setObject:[NSNumber numberWithInt:self.repeat] forKey:ALARM_REPEAT];
	
	return alarmInfo;
}

/** get NSDateComponents **/
- (NSDateComponents *)getDateComponents:(NSDate *)date{
	NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];

	
	NSInteger unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSWeekdayCalendarUnit |
		NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit;
	
	return [calendar components:unitFlags fromDate:date];
}

/** if repeat **/
- (BOOL)ifRepeat:(NSDate *)date{
	NSDateComponents *comps = [self getDateComponents:date];
	
	//repeatDay Example '0111101',
	//The digit,first from right side，which means repeat this alarm on Sunday
	int repeatDay = self.repeat;
	int weekDay = [comps weekday];
	
	for (int i = 1; i < weekDay; i++) {
		repeatDay = repeatDay/10;
	}
	
	repeatDay%10 ? NSLog(@"ifRepeat date:%@\n weekday:%d", date, weekDay) : NSLog(@" ");
	
	return repeatDay%10;
}

- (BOOL)hasNotification:(NSDate *)date{
	for (UILocalNotification *notification in ownNotifications) {
		if([notification.fireDate isEqualToDate:date]) {
			return YES;	
		}
	}
	
	return NO;
}

#pragma mark -
#pragma mark Unclassified

/** Init a exist alarm 
 ** path: this alarm's record file path
 **/
- (id)initWithPath:(NSString *)path {
	if (self = [super init]) {
		[self readInfo:path];
		ownNotifications = [[NSMutableArray alloc] initWithCapacity:0];
		[self getOwnNotification];
		self.isActive ? [self addNotification] : [self removeNotication];
		
		alarmCtrl = [[ACAlarmController alloc] init];
		alarmCtrl.alarm = self;
	}
	
	return self;
}

/** Create a new alarm with info**/
- (id)init{
	if (self = [super init]) {
		ownNotifications = [[NSMutableArray alloc] initWithCapacity:0];
		
		self.title = NSLocalizedString(@"Alarm", nil);
		self.sondName = defaultSound;
		self.isActive = YES;
		self.repeat = 0;
		self.createDate = [NSDate date];
		ownNotifications = [[NSMutableArray alloc] initWithCapacity:0];
		
		//clear seconds
		NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
		[dateFormatter setDateFormat:@"yyyyMMddHHmmss"];
		NSString *tempDateString = [dateFormatter stringFromDate:[NSDate date]];
		tempDateString = [tempDateString substringToIndex:[tempDateString length] - 2];
		tempDateString = [NSString stringWithFormat:@"%@00", tempDateString];
		
		self.fireTime = [dateFormatter dateFromString:tempDateString];
	}
	
	return self;
}

- (void)dealloc{
	[lblTime release];
	[lblRepeat release];
	[lblTitle release];
	[alarmSwitch release];
	[alarmCtrl release];
	
	[alarmIdentifier release];
	[title release];
	[sondName release];
	[createDate release];
	[fireTime release];
	
	[super dealloc];
}

#pragma mark -
#pragma mark Notification control

/** Private: add a notification with date **/
- (void)addNotificationWithDate:(NSDate *)date{
	UILocalNotification *notification = [[UILocalNotification alloc] init];
	
	notification.fireDate = date;
	notification.timeZone = [NSTimeZone defaultTimeZone];
	notification.soundName = self.sondName;
	notification.repeatInterval = NSMinuteCalendarUnit;
	notification.alertBody = self.title;
	notification.userInfo = [self getInfoDictionary];
	
	[ownNotifications addObject:notification];
	[[UIApplication sharedApplication] scheduleLocalNotification:notification];
	
	[notification release];
	
	NSLog(@"add notification succeeded:%@", notification);
}

/** Add local notification for this alarm**/
- (void)addNotification{
	[self nextFire];
	[self writeInfo];
	
	//Add UILocalNotification 
	if (self.repeat == 0) {
		if ([ownNotifications count] == 0) {
			[self addNotificationWithDate:self.fireTime];
		}
		
		return;
	}
	
	int j = 0;
	
	for (int i = 0; i < (ALARM_NOTIFICATION_NUM - [ownNotifications count]); i++) {
		while ([self hasNotification:[self.fireTime dateByAddingTimeInterval:aDay * (i + j)] ] ||
				 ![self ifRepeat:[self.fireTime dateByAddingTimeInterval:aDay * (i + j)] ]){
			j++;
		}
		[self addNotificationWithDate:[self.fireTime dateByAddingTimeInterval:aDay * (i + j)]];
	}
}

/** Remove this alarm's all notification **/
- (void)removeNotication{
	UIApplication *app = [UIApplication sharedApplication];
	
	for (UILocalNotification *notification in ownNotifications) {
		[app cancelLocalNotification:notification];
	}
	
	[ownNotifications removeAllObjects];
}

/** Get own notification**/
- (void)getOwnNotification{
	UIApplication *app = [UIApplication sharedApplication];
	NSArray *appNotifications = [app scheduledLocalNotifications];
	
	for (UILocalNotification *notification in appNotifications) {
		if ([ [notification.userInfo objectForKey:ALARM_ID] isEqualToString:self.alarmIdentifier]) {
			[ownNotifications addObject:notification];
			NSLog(@"getOwnNotifications%@:%@", self.alarmIdentifier, notification);
		}
	}
}

#pragma mark -
#pragma mark Alarm Control

/** Turn on this alarm **/
- (void)turnOn{
	[self addNotification];
	self.isActive = YES;
}

/** turnOff this alarm **/
- (void)turnOff{
	[self removeNotication];
	self.isActive = NO;
}

/** Turn on or off this alarm **/
- (void)switchAlarm:(UISwitch *)sender{
	sender.on ? [self turnOn] : [self turnOff];
	[self writeInfo];
}

- (void) deleteAlarm{
	[self removeNotication];
	deleteFile([NSString stringWithFormat:@"%@.alarm", self.alarmIdentifier]);
}

#pragma mark -
#pragma mark Info control

/** record alarm **/
- (void)writeInfo{
	NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
	[dateFormatter setDateFormat:@"yyyyMMddHHmmss"];
	self.alarmIdentifier = [dateFormatter stringFromDate:createDate];
	[dateFormatter release];
	
	NSMutableDictionary *alarmInfo = [self getInfoDictionary];
	
	[alarmInfo writeToFile:getFileFullPath([NSString stringWithFormat:@"%@.alarm", self.alarmIdentifier])
				atomically:YES];
}

/** read alarm's info **/
- (void)readInfo:(NSString *)path{
	NSFileManager *appFileManager = [NSFileManager defaultManager];
	
	if ([appFileManager fileExistsAtPath:path] && [appFileManager isReadableFileAtPath:path]) {
		NSDictionary *alarmInfo = [NSDictionary dictionaryWithContentsOfFile:path];
		
		self.alarmIdentifier = [alarmInfo objectForKey:ALARM_ID];
		self.title = [alarmInfo objectForKey:ALARM_TITLE];
		self.sondName = [alarmInfo objectForKey:ALARM_SOUND_NAME];
		self.createDate = [alarmInfo objectForKey:ALARM_CREATE_DATE];
		self.fireTime = [alarmInfo objectForKey:ALARM_FIRE_TIME];
		self.isActive = [[alarmInfo objectForKey:ALARM_IS_ACTIVE] boolValue];
		self.repeat = [[alarmInfo objectForKey:ALARM_REPEAT] intValue];
		
		NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
		[dateFormatter setDateFormat:@"HHmm"];
		
		self.index = [[dateFormatter stringFromDate:self.fireTime] intValue];
	} 
}

/** snooze **/
- (void)snooze{
	[self stopAlarm];
	[self addNotificationWithDate:[NSDate dateWithTimeIntervalSinceNow:600]];
}

/** Stop the fire alarm **/
- (void)stopAlarm{
	[self nextFire];
	
	for (UILocalNotification *noti in ownNotifications) {
		if ([noti.fireDate compare:self.fireTime] < 0) {
			[[UIApplication sharedApplication] cancelLocalNotification:noti];
		}
	}
	if (repeat == 0) {
		self.isActive = NO;
		[self writeInfo];
		[self removeNotication];
	}
}

@end
